﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ScheduleUtil
{
    public static class Schedule
    {
        /// <summary>
        /// 时间表集
        /// </summary>
        private static Dictionary<string, WeekTimesTable> timesTables = new();
        /// <summary>
        /// 设置一个时间表
        /// </summary>
        /// <param name="weekTimesTable"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        public static bool SetTimesTable(WeekTimesTable weekTimesTable, string key = "default")
        {
            if (key == null || key.Length <= 0)
            {
                return false;
            }

            if (!timesTables.ContainsKey(key))
            {
                timesTables.TryAdd(key, weekTimesTable);
            }
            else
            {
                timesTables[key] = weekTimesTable;
            }

            return true;
        }
        /// <summary>
        /// 
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public static WeekTimesTable? GetTimesTable(string key = "default")
        {
            if (!timesTables.ContainsKey(key))
            {
                return null;
            }
            else
            { 
                return timesTables[key];
            }
        }

        /// <summary>
        /// 判断当前是否时间表内
        /// </summary>
        /// <param name="key"></param>
        /// <param name="addMinute"></param>
        /// <param name="subMinute"></param>
        /// <returns></returns>
        public static bool CheckInTime(string key = "default")
        {
            if (key == null || key.Length <= 0)
            {
                return true;
            }

            if (timesTables.ContainsKey(key)) 
            { 
                return timesTables[key].InBroadcasTime();
            }

            return true;
        }
    }

    /// <summary>
    /// 一周时间表
    /// </summary>
    public class WeekTimesTable
    {
        /// <summary>
        /// 提前告警分钟数
        /// </summary>
        public int addMinute { get; set; } = 0;
        /// <summary>
        /// 延时告警分钟数
        /// </summary>
        public int subMinute { get; set; } = 0;
        private bool inTimePre { get; set; } = false;
        private event Action<Object> OnChange;
        /// <summary>
        /// 一周
        /// </summary>
        public DayTimesFlag[] dayTimesFlags { get; set; } = new DayTimesFlag[7];
        public WeekTimesTable(){ }
        public WeekTimesTable(Action<Object> OnChange, int addMinute, int subMinute)
        {
            this.addMinute = addMinute;
            this.subMinute = subMinute;
            this.OnChange = OnChange;
            if (OnChange != null)
            {
                new Thread(TimerMonitor).Start();
            }
        }
        /// <summary>
        /// 设置监听
        /// </summary>
        /// <param name="OnChange"></param>
        public void SetOnChange(Action<Object> OnChange)
        {
            this.OnChange = OnChange;
            if (OnChange != null && this.OnChange == null)
            {
                new Thread(TimerMonitor).Start();
            }
        }
        /// <summary>
        /// 当前是否在时间表内
        /// </summary>
        /// <param name="addMinute">提前告警分钟数</param>
        /// <param name="subMinute">延时告警分钟数</param>
        /// <returns></returns>
        public bool InBroadcasTime()
        {
            //当前星期几
            int weekNum = (int)DateTime.Now.DayOfWeek;
            DayTimesFlag dayTimesFlag = dayTimesFlags[weekNum];
            return dayTimesFlag == null ? true : dayTimesFlag.InBroadcasTime(addMinute, subMinute);
        }
        /// <summary>
        /// 提供触发事件
        /// </summary>
        private void TimerMonitor()
        {
            Thread.Sleep(5 * 1000);
            inTimePre = InBroadcasTime();
            while (true) 
            {
                bool inTime = InBroadcasTime();
                if (inTime != inTimePre)
                {
                    OnChange?.Invoke(inTime ? 1 : 0);
                }
                Thread.Sleep(1000);
            }
        }
    }
}
